#pragma once
#include "CBuilder.h"

enum eProjectType : char
{
	PROJECT_BLANK,
	PROJECT_MAIN,
	PROJECT_SCRIPT,
	PROJECT_CLEO,
	PROJECT_MOD
};

enum eProjectFileType : char
{
	PF_NONE,
	PF_SCRIPT,
	PF_SUBSCRIPT,
	PF_INCLUDE,
};

enum eProjectFileAction : char
{
	ACTION_PARSE,
	ACTION_COMPILE,
	ACTION_BUILD,
	ACTION_MERGE,
	ACTION_ASSEMBLE,
	ACTION_COPY,
	ACTION_RUNEXE,
	ACTION_IGNORE,
};

class CScript;
class CSubScript;

class CProjectFile
{
	friend class CProject;
	bool						m_bIsUsed;
	bool						m_bMergedWith;
	bool						m_bBuildFailed;
	eProjectFileType			m_bType;
	eProjectFileAction		m_bAction;

	inline void						ResetBuildFail()						{m_bBuildFailed = false;}

protected:
	inline void						FailBuild()							{m_bBuildFailed = true;}
	inline void						IsMergedWith(bool b)					{m_bMergedWith = b;}

public:
	CProjectFile(eProjectFileType bType = PF_NONE, eProjectFileAction bAction = ACTION_BUILD)
					:	m_bIsUsed(true),
						m_bMergedWith(false),
						m_bBuildFailed(false),
						m_bType(bType),
						m_bAction(bAction)
	{
	}
	virtual	~CProjectFile(){};
	
	inline bool						IsMergedWith() const					{return m_bMergedWith;}
	inline bool						IsUsed() const						{return m_bIsUsed;}
	inline bool						HasBuildFailed()	 const				{return m_bBuildFailed;}
	inline eProjectFileType			GetProjectFileType() const			{return m_bType;}
	inline eProjectFileAction		GetProjectFileAction() const			{return m_bAction;}
	
	virtual	void					Parse(){};
	virtual void					Compile(){};
	virtual void					Build(){};
	virtual void					Merge(){};
	virtual void					Assemble(){};
	virtual void					Copy(){};
	virtual void					RunExe(){};
	virtual void					Ignore(){};
};

class CProject : public CLListEx<CProjectFile*>
{
	eProjectType				m_bType;
	bool						m_bIsDraft;
	bool						m_bIsActive;

public:
	CProject()
	{
		m_bType = PROJECT_BLANK;
		m_bIsDraft = false;
		m_bIsActive = true;
	}

	inline void			SetType(eProjectType eType)					{m_bType = eType;}
	inline eProjectType	GetType()									{return m_bType;}

	bool		Build()
	{
		int i = 0;

		for(auto pLink = Begin(); pLink != Bad(); ++pLink)
		{
			if(!pLink->IsUsed()) continue;
			switch(pLink->GetProjectFileAction())
			{
			case ACTION_PARSE:
				pLink->Parse();
				break;
			case ACTION_COMPILE:
				pLink->Compile();
				break;
			case ACTION_BUILD:
				pLink->Build();
				break;
			case ACTION_MERGE:
				pLink->Merge();
				break;
			case ACTION_ASSEMBLE:
				pLink->Assemble();
				break;
			case ACTION_COPY:
				pLink->Copy();
				break;
			case ACTION_RUNEXE:
				pLink->RunExe();
				break;
			case ACTION_IGNORE:
				pLink->Ignore();
				break;
			default: continue;
			}

			++i;
			
			if(pLink->HasBuildFailed())
			{
				pLink->ResetBuildFail();
				return false;
			}
		}

		if(i == 0) throw(SCRambl.GetText("PROJECTS", "M104"));

		Merge();
		return true;
	}

	bool			Merge();
};

#pragma pack(push, 1)
struct ProjectFileHeader
{
	char sig[3];

	ProjectFileHeader()
	{
		strncpy(sig, "SCR", 3);
	};
};

class CProjectPacked
{
	ProjectFileHeader		Header;
	char					m_bTargetGame;
	eProjectType			m_bType;
	bool					m_bIsMultiFile;
	bool					m_bOwnDataDir;
};
#pragma pack(pop)